10分钟使用kubeadm搭建高可用Kubernetes集群

如何10分钟快速搭建一个高可用的Kubernetes集群。

Key Value
OS CentOS 7
Docker 建议 >= 13.1
Kubernetes 1.13.0
Kubernetes Master HA*3
Kubernetes etcd HA*3
网络 flannel
LB Nginx或HAProxy

前置准备

Docker

安装并启动docker,这里不做赘述。

安装包

准备etcd、kubeadm、kubectl、kubelet、kubernetes-cni、cri-tools等安装包。

1
wget https://github.com/etcd-io/etcd/releases/download/v3.2.22/etcd-v3.2.22-linux-amd64.tar.gz

1
2
3
4
5
6
7
8
vim /etc/yum.repo.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://packages.cloud.google.com/yum/repos/kubernetes-el7-x86_64
enabled=1
gpgcheck=1
repo_gpgcheck=1
gpgkey=https://packages.cloud.google.com/yum/doc/yum-key.gpg https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg
1
yum install --downloadonly --downloaddir ./ kubelet kubeadm kubectl kubernetes-cni cri-tools
镜像
1
2
3
4
5
6
docker pull k8s.gcr.io/kube-proxy:v1.13.0
docker pull k8s.gcr.io/kube-apiserver:v1.13.0
docker pull k8s.gcr.io/kube-controller-manager:v1.13.0
docker pull k8s.gcr.io/kube-scheduler:v1.13.0
docker pull k8s.gcr.io/coredns:1.2.6
docker pull k8s.gcr.io/pause:3.1
网络插件

使用部署和运维最简单的flannel。

1
wget https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml

LB

无论使用哪种LB工具,需要保证以下几点:

  1. 分配到三个master节点的权重均等。
  2. 从VIP的6443端口转发到后端的三个master节点的相同端口。
  3. 从VIP的2379和2380端口转发到后端的三个etcd节点的相同端口。
  4. 各个master节点之间、master到VIP、node到VIP的网络需畅通。

假设此例中的VIP为10.107.105.241。

节点

假设master节点的IP如下,同时作为etcd集群的节点:
10.107.105.207
10.107.116.238
10.107.116.213

etcd安装步骤

1. 安装etcd

采用yum源安装,使用的版本为3.2.22。

1
yum install -y etcd

2. etcd服务配置

对三台etcd节点的etcd服务均设置相同的数据目录。

1
vim /lib/systemd/system/etcd.service

1
2
3
4
5
[Service]
workingDirectory=/data/etcd
EnvironmentFile=-/etc/etcd/etcd.conf
User=etcd
...
3. etcd数据目录

对三台etcd节点,在外部挂载磁盘的/data路径下创建etcd的数据目录,并赋予正确的权限。

1
2
mkdir -p /data/etcd
chown etcd:etcd

4. etcd详细配置

假设设置10.107.105.207为etcd集群的leader,则将其ETCD_INITIAL_CLUSTER_STATE设置为"new",其他两台设置为"exist";同时他们配置相同的ETCD_INITIAL_CLUSTERETCD_INITIAL_CLUSTER_TOKEN
如下为leader 10.107.105.207的/etc/etcd/etcd.conf配置。

1
2
3
4
5
6
7
8
9
10
11
#[Member]
ETCD_DATA_DIR="/data/etcd/default.etcd"
ETCD_LISTEN_PEER_URLS="http://10.107.105.207:2380"
ETCD_LISTEN_CLIENT_URLS="http://10.107.105.207:2379,http://127.0.0.1:2379"
ETCD_NAME="etcd1"
#[Clustering]
ETCD_INITIAL_ADVERTISE_PEER_URLS="http://10.107.105.207:2380"
ETCD_ADVERTISE_CLIENT_URLS="http://10.107.105.207:2379,http://127.0.0.1:2379"
ETCD_INITIAL_CLUSTER="etcd1=http://10.107.105.207:2380,etcd2=http://10.107.116.238:2380,etcd3=http://10.107.116.213:2380"
ETCD_INITIAL_CLUSTER_TOKEN="mlss-k8s-etcd"
ETCD_INITIAL_CLUSTER_STATE="new"

如下分别为10.107.116.238及10.107.116.213的/etc/etcd/etcd.conf配置。

1
2
3
4
5
6
7
8
9
10
11
#[Member]
ETCD_DATA_DIR="/data/etcd/default.etcd"
ETCD_LISTEN_PEER_URLS="http://10.107.116.238:2380"
ETCD_LISTEN_CLIENT_URLS="http://10.107.116.238:2379,http://127.0.0.1:2379"
ETCD_NAME="etcd2"
#[Clustering]
ETCD_INITIAL_ADVERTISE_PEER_URLS="http://10.107.116.238:2380"
ETCD_ADVERTISE_CLIENT_URLS="http://10.107.116.238:2379,http://127.0.0.1:2379"
ETCD_INITIAL_CLUSTER="etcd1=http://10.107.105.207:2380,etcd2=http://10.107.116.238:2380,etcd3=http://10.107.116.213:2380"
ETCD_INITIAL_CLUSTER_TOKEN="mlss-k8s-etcd"
ETCD_INITIAL_CLUSTER_STATE="exist"

1
2
3
4
5
6
7
8
9
10
11
#[Member]
ETCD_DATA_DIR="/data/etcd/default.etcd"
ETCD_LISTEN_PEER_URLS="http://10.107.116.213:2380"
ETCD_LISTEN_CLIENT_URLS="http://10.107.116.213:2379,http://127.0.0.1:2379"
ETCD_NAME="etcd3"
#[Clustering]
ETCD_INITIAL_ADVERTISE_PEER_URLS="http://10.107.116.213:2380"
ETCD_ADVERTISE_CLIENT_URLS="http://10.107.116.213:2379,http://127.0.0.1:2379"
ETCD_INITIAL_CLUSTER="etcd1=http://10.107.105.207:2380,etcd2=http://10.107.116.238:2380,etcd3=http://10.107.116.213:2380"
ETCD_INITIAL_CLUSTER_TOKEN="mlss-k8s-etcd"
ETCD_INITIAL_CLUSTER_STATE="exist"
4. 启动etcd

至此etcd集群配置完毕,需要将其启动,在leader及另外两台节点上执行如下操作。

1
2
systemctl daemon-reload
systemctl restart etcd

节点全部启动完毕后,在任意一台机器上验证:

1
etcdctl member list

Kubernetes安装步骤

对于集群中的每个master节点,需进行步骤1-6。

1. 关闭swap
1
2
3
swapoff -a
vim /etc/fstab
# 注释掉有swap的一行
2. 关闭防火墙
1
systemctl stop firewalld;systemctl disable firewalld;setenforce 0
3. 禁用selinux
1
2
vim /etc/selinux/config
# 设置SELINUX=disabled
4. 启用bridge-nf
1
sysctl net.bridge.bridge-nf-call-iptables=1
5. cgroup driver设置

理论上,kubelet的cgroup driver与docker的cgroup driver需保持一致。

  • 如果在docker的配置中(/lib/systemd/system/docker.service/etc/sysconfig/docker*/etc/docker/daemon.json),设置了native.cgroupdriver=cgroupfs,则在kubelet的配置中(/etc/systemd/system/kubelet.service.d/10-kubeadm.conf)设置--cgroup-driver=cgroupfs
  • 如果docker的native.cgroupdriver=systemd,则在kubelet中设置--cgroup-driver=systemd

然而在实际中:

  • 如果docker中设置了native.cgroupdriver=cgroupfs,kubelet不做任何额外配置,节点可以正常启动Kubelet。
  • 如果docker中设置了native.cgroupdriver=systemd,kubelet不做任何额外配置,节点仍然可以正常启动Kubelet,但/var/lib/kubelet/config.yaml中显示cgroupDriver: cgroupfs,说明kubelet默认的cgroup driver为cgroupfs
6. 设置启动参数
1
vim kubeadm.conf

创建初始化配置文件设置启动参数。

  • apiServerCertSANs设置所有master节点的IP、hostname及LB的VIP。
  • controlPlaneEndpoint设置为<VIP>:6443,6443为apiserver的默认端口。
  • etcd设置为external,并填写上述所有etcd节点的IP及2379端口。
  • networking设置pod子网网段,根据CNI的需求而不同。
  • controllerManagerExtraArgsschedulerExtraArgs设置address0.0.0.0,将其暴露给集群,此设置是出于监控采集controller-manager及scheduler的metrics的考虑。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
apiVersion: kubeadm.k8s.io/v1alpha3
kind: ClusterConfiguration
kubernetesVersion: 1.13.0
apiServerCertSANs:
- 10.107.105.241
- 10.107.105.207
- 10.107.116.238
- 10.107.116.213
- mlssdi010001
- mlssdi010004
- mlssdi010005
controlPlaneEndpoint: "10.107.105.241:6443"
etcd:
external:
endpoints:
- http://10.107.105.207:2379
- http://10.107.116.238:2379
- http://10.107.116.213:2379
networking:
podSubnet: 10.244.0.0/16
controllerManagerExtraArgs:
address: 0.0.0.0
schedulerExtraArgs:
address: 0.0.0.0
7. 启动第一个master

在第一台节点上使用该配置启动集群。

1
kubeadm init --config kubeadm.conf

记录下最后输出的kubeadm join命令。

8. 启动其他master

待第一个master节点完成初始化后,将/etc/kubernetes/pki目录下的所有文件拷贝至其他两个节点的相同目录下。
使用相同的配置依次启动其他两个master。

1
kubeadm init --config kubeadm.conf

记录下最后输出的kubeadm join命令。

9. kubectl

在任意一台master节点上,使用以下命令来给kubectl添加配置。

1
2
3
mkdir -p $HOME/.kube
cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
chown $(id -u):$(id -g) $HOME/.kube/config

使用kubectl get no验证,应该能看到三台NotReady的master。

10. CNI

这里我们采用flannel作为CNI插件,使用以下命令创建网络组件。

1
kubectl apply -f kube-flannel.yml

11. 加入node

步骤7和8生成的join命令格式如下:

1
kubeadm join 10.107.105.241:6443 --token <token> --discovery-token-ca-cert-hash sha256:<hash>

三个master节点初始化后的token是不同的,但discovery-token-ca-cert-hash是相同的,因此对于node来说,使用任意一台master生成的token来join即可。

常见问题

coredns启动失败

coredns处于CrashLoopBackoff,这是由于coredns的默认配置的问题,执行以下命令即可:

1
2
3
kubectl -n kube-system get deployment coredns -o yaml | \
sed 's/allowPrivilegeEscalation: false/allowPrivilegeEscalation: true/g' | \
kubectl apply -f -

清理

1. 重置数据

在所有机器上使用kubeadm清理数据。

1
2
3
kubeadm reset
rm -rf /etc/kubernetes
rm -rf $HOME/.kube

2. 重置网络

在所有机器上需要清理掉CNI网络的相关内容。

1
2
ifconfig flannel.1 down && ip link delete flannel.1
ifconfig cni0 down && ip link delete cni0

3. 清空etcd

在etcd节点上,直接删除etcd存放的Kubernetes集群数据即可。

1
rm -rf /data/etcd/default.etcd